vue + el

您所在的位置:网站首页 mfc canvas 缩放 vue + el

vue + el

2023-06-30 14:29| 来源: 网络整理| 查看: 265

一、背景

前端对图片进行 剪裁 或者 大小进行压缩 都是比较场景的需求。但是这次接到一个 将图片尺寸缩小 的需求,为啥呢?因为在前端上传到服务器后,有个功能会导出 word,而图片就会放到里面去导出,而图片尺寸太大,显示会有问题;例如简历个人信息里面的身份证、学历、头像等照片(这种问题其实我觉得应该由后端处理,但既然知道了,就研究研究)。

二、实现思路

有个问题需要先确定:缩放实现在上传前还是上传后,区别是什么? el-upload组件中一般都有大图预览功能,即el-image 中的预览功能previewSrcList;

上传前缩小:保存后的图片较小,预览大图也不能看到原始尺寸(没保存前可以看到)上传后缩小:需要上传两张图,并且小图需要做无感上传,原始图和缩小后的图片,并且需要定义区分规则,怎么获取大图,怎么获取小图

由于项目中对大图展示要求不高,故采用 上传前缩小 实现;

三、代码实现

el-upload 二次封装代码不尽相同,故在此只展现压缩相关核心代码

compressImgSize(file) { // 压缩图片 // file 里面没有url 字段(el-upload自带,用于图片展示的临时路径),则通过URL.createObjectURL(file)转化为临时路径 // const fileUrl = URL.createObjectURL(file) // const image = new Image(); // image.src = fileUrl; const image = new Image(); image.src = file.url; image.onload = (e) => { // onload 才能获取到图片真实的宽高 console.log('image.width', image, image.width, image.height) if (image.width > 0 && image.height > 0) { const oldScale = Number((image.width / image.height).toFixed(2)); let maxWidth = 200, maxHeight = 200; // 定义缩放后的最大宽高 let targetWidth = image.width, targetHeight = image.height; // 图片缩放后的真实宽高, 默认为图片的原始尺寸 if (targetWidth > maxWidth) { // 目标宽度大于最大宽度 targetWidth = maxWidth; targetHeight = targetWidth / oldScale; } //缩放后高度仍然大于最大高度继续按比例缩小 if (targetHeight > maxHeight) { targetHeight = maxHeight targetWidth = targetHeight * oldScale; } const canvas = document.createElement('canvas'); // 创建一个canvas节点 const context = canvas.getContext('2d'); canvas.width = targetWidth; // 设置canvas的宽高 canvas.height = targetHeight; context.drawImage(image, 0, 0, targetWidth, targetHeight); // 将图片绘制到canvas内部 const imageBase64 = canvas.toDataURL('image', 0.92);//canvas导出成为base64 this.upData.file = this.base64ToFile(imageBase64, 'file') // 将base64图片转为 file 对象 this.$refs.upload.submit(); // 触发上传 } } }, // base64图片转file的方法(base64图片, 设置生成file的文件名) base64ToFile(base64, fileName) { // 将base64按照 , 进行分割 将前缀 与后续内容分隔开 let data = base64.split(','); // 利用正则表达式 从前缀中获取图片的类型信息(image/png、image/jpeg、image/webp等) let type = data[0].match(/:(.*?);/)[1]; // 从图片的类型信息中 获取具体的文件格式后缀(png、jpeg、webp) let suffix = type.split('/')[1]; // 使用atob()对base64数据进行解码 结果是一个文件数据流 以字符串的格式输出 const bstr = window.atob(data[1]); // 获取解码结果字符串的长度 let n = bstr.length // 根据解码结果字符串的长度创建一个等长的整形数字数组 // 但在创建时 所有元素初始值都为 0 const u8arr = new Uint8Array(n) // 将整形数组的每个元素填充为解码结果字符串对应位置字符的UTF-16 编码单元 while (n--) { // charCodeAt():获取给定索引处字符对应的 UTF-16 代码单元 u8arr[n] = bstr.charCodeAt(n) } // 利用构造函数创建File文件对象 // new File(bits, name, options) const file = new File([u8arr], `${fileName}.${suffix}`, { type: type }) // 将File文件对象返回给方法的调用者 return file; }

注意点:

compressImgSize 压缩方法调用位置在 上传文件之前的钩子 before-upload 或者是 文件状态改变时的钩子 on-change上传文件之前的钩子 before-upload 拿到的 file 没有url,需要通过 URL.createObjectURL(file) 转化文件状态改变时的钩子 on-change 里面有临时路径 url,可直接使用this.$refs.upload.submit() 手动触发的上传方法,文件默认还是原始图片,需要通过配置 data: { file: this.upData.fil } => 上传时附带的额外参数 实现上传缩小后的图片;但el-upload默认在上传时携带了file参数并不可删除(很麻烦),所以可以通过配置 name="file2" 将原本的file => 修改成file2 即可。

ps: 最佳方式还是由后端重新写一个 接口A,在导出接口中调用 接口A 时,将图片临时处理缩小后返回即可,这种操作不能影响到前端大图展示  

文章仅为本人学习过程的一个记录,仅供参考,如有问题,欢迎指出!



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3